Repository navigation
Conversation
|
Important Review skippedToo many files! This PR contains 304 files, which is 204 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. Usage-priced reviews support at most 300 files. ⚙️ Run configuration
⛔ Files ignored due to path filters: 1
📒 Files selected for processing: 304
You can disable this status message by setting the
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
e7182e2 to
4ace8e7
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
One or more issues must be addressed before approval.
Review effort: Lite
Findings: 1
Open (5)
What changed in this PR
Splits the SDK into the ably-pubsub-server distribution and updates public imports, factories, synchronous generation, documentation, and tests.
Changes:
- Migrates modules and tests to
ably.pubsub. - Adds factory/prototype-based client construction.
- Updates packaging, documentation, and release configuration.
| File | Description |
|---|---|
| UPDATING.md | Updated as part of this pull request. |
| test/uts/rest/unit/types/token_types_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/types/presence_message_types_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/types/paginated_result_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/types/options_types_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/types/mutable_message_types_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/types/message_types_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/types/error_types_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/time_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/stats_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/rest_client_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/push/push_device_registrations_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/push/push_channels_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/push/push_channel_subscriptions_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/push/push_admin_publish_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/presence/rest_presence_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/fallback_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/encoding/msgpack_interop_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/encoding/message_encoding_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/channels_collection_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/channel/update_delete_message_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/channel/rest_channel_attributes_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/channel/publish_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/channel/publish_result_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/channel/message_versions_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/channel/idempotency_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/channel/history_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/channel/get_message_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/channel/annotations_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/batch_publish_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/batch_presence_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/auth/token_renewal_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/auth/token_details_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/auth/revoke_tokens_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/auth/client_id_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/auth/authorize_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/auth/auth_scheme_test.py | Updated as part of this pull request. |
| test/uts/rest/unit/auth/auth_callback_test.py | Updated as part of this pull request. |
| test/uts/rest/integration/time_stats_test.py | Updated as part of this pull request. |
| test/uts/rest/integration/revoke_tokens_test.py | Updated as part of this pull request. |
| test/uts/rest/integration/push_channels_test.py | Updated as part of this pull request. |
| test/uts/rest/integration/push_admin_test.py | Updated as part of this pull request. |
| test/uts/rest/integration/publish_test.py | Updated as part of this pull request. |
| test/uts/rest/integration/proxy/rest_fallback_test.py | Updated as part of this pull request. |
| test/uts/rest/integration/presence_test.py | Updated as part of this pull request. |
| test/uts/rest/integration/pagination_test.py | Updated as part of this pull request. |
| test/uts/rest/integration/mutable_messages_test.py | Updated as part of this pull request. |
| test/uts/rest/integration/batch_presence_test.py | Updated as part of this pull request. |
| test/uts/rest/integration/auth_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/presence/realtime_presence_subscribe_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/presence/realtime_presence_reentry_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/presence/realtime_presence_history_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/presence/realtime_presence_get_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/presence/realtime_presence_enter_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/presence/realtime_presence_channel_state_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/presence/presence_sync_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/presence/presence_map_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/presence/local_presence_map_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/connection/when_state_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/connection/update_events_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/connection/server_initiated_reauth_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/connection/heartbeat_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/connection/forwards_compatibility_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/connection/fallback_hosts_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/connection/error_reason_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/connection/connection_recovery_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/connection/connection_ping_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/connection/connection_open_failures_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/connection/connection_id_key_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/connection/connection_failures_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/connection/backoff_jitter_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/connection/auto_connect_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/client/realtime_timeouts_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/client/realtime_time_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/client/realtime_stats_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/client/realtime_request_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/client/realtime_client_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/message_field_population_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channels_collection_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_when_state_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_update_delete_message_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_subscribe_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_state_events_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_server_initiated_detach_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_publish_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_publish_pending_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_properties_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_options_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_message_versions_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_history_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_get_message_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_error_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_detach_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_delta_decoding_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_connection_state_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_attributes_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_attach_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_annotations_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/channels/channel_additional_attached_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/auth/token_expiry_non_renewable_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/auth/realtime_authorize_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/auth/connection_auth_test.py | Updated as part of this pull request. |
| test/uts/realtime/unit/auth/auth_callback_errors_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/proxy/rest_faults_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/proxy/presence_reentry_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/proxy/heartbeat_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/proxy/connection_resume_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/proxy/connection_open_failures_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/proxy/channel_faults_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/proxy/auth_reauth_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/presence/presence_sync_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/presence_lifecycle_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/mutable_messages_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/delta_decoding_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/connection/connection_failures_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/connection_lifecycle_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/channels/channel_subscribe_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/channels/channel_publish_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/channels/channel_attach_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/channel_history_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/auth/token_request_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/auth/token_renewal_test.py | Updated as part of this pull request. |
| test/uts/realtime/integration/auth_test.py | Updated as part of this pull request. |
| test/uts/README.md | Updated as part of this pull request. |
| test/uts/helpers/sandbox.py | Updated as part of this pull request. |
| test/uts/helpers/presence.py | Updated as part of this pull request. |
| test/uts/helpers/mock_websocket.py | Updated as part of this pull request. |
| test/uts/helpers/mock_websocket_test.py | Updated as part of this pull request. |
| test/uts/helpers/mock_http_test.py | Updated as part of this pull request. |
| test/uts/helpers/clock.py | Updated as part of this pull request. |
| test/uts/helpers/client.py | Updated as part of this pull request. |
| test/unit/websockettransport_test.py | Updated as part of this pull request. |
| test/unit/pubsub_server_test.py | Updated as part of this pull request. |
| test/unit/options_test.py | Updated as part of this pull request. |
| test/unit/mutable_message_test.py | Updated as part of this pull request. |
| test/unit/message_test.py | Updated as part of this pull request. |
| test/unit/http_test.py | Updated as part of this pull request. |
| test/unit/clock_test.py | Updated as part of this pull request. |
| test/unit/annotation_test.py | Updated as part of this pull request. |
| test/ably/utils.py | Updated as part of this pull request. |
| test/ably/testapp.py | Updated as part of this pull request. |
| test/ably/realtime/realtimeresume_test.py | Updated as part of this pull request. |
| test/ably/realtime/realtimepresence_test.py | Updated as part of this pull request. |
| test/ably/realtime/realtimeinit_test.py | Updated as part of this pull request. |
| test/ably/realtime/realtimeconnection_test.py | Updated as part of this pull request. |
| test/ably/realtime/realtimechannelmutablemessages_test.py | Updated as part of this pull request. |
| test/ably/realtime/realtimechannel_vcdiff_test.py | Updated as part of this pull request. |
| test/ably/realtime/realtimechannel_test.py | Updated as part of this pull request. |
| test/ably/realtime/realtimechannel_publish_test.py | Updated as part of this pull request. |
| test/ably/realtime/realtimeauth_test.py | Updated as part of this pull request. |
| test/ably/realtime/realtimeannotations_test.py | Updated as part of this pull request. |
| test/ably/realtime/presencemap_test.py | Updated as part of this pull request. |
| test/ably/realtime/eventemitter_test.py | Updated as part of this pull request. |
| test/ably/realtime/deltadecoding_test.py | Updated as part of this pull request. |
| test/ably/http/httptoken_test.py | Updated as part of this pull request. |
| test/ably/http/httptime_test.py | Updated as part of this pull request. |
| test/ably/http/httpstats_test.py | Updated as part of this pull request. |
| test/ably/http/httprequest_test.py | Updated as part of this pull request. |
| test/ably/http/httppush_test.py | Updated as part of this pull request. |
| test/ably/http/httppresence_test.py | Updated as part of this pull request. |
| test/ably/http/httppaginatedresult_test.py | Updated as part of this pull request. |
| test/ably/http/httphttp_test.py | Updated as part of this pull request. |
| test/ably/http/httpcrypto_test.py | Updated as part of this pull request. |
| test/ably/http/httpchannelstatus_test.py | Updated as part of this pull request. |
| test/ably/http/httpchannels_test.py | Updated as part of this pull request. |
| test/ably/http/httpchannelpublish_test.py | Updated as part of this pull request. |
| test/ably/http/httpchannelmutablemessages_test.py | Updated as part of this pull request. |
| test/ably/http/httpchannelhistory_test.py | Updated as part of this pull request. |
| test/ably/http/httpcapability_test.py | Updated as part of this pull request. |
| test/ably/http/httpannotations_test.py | Updated as part of this pull request. |
| test/ably/http/encoders_test.py | Updated as part of this pull request. |
| README.md | Updated as part of this pull request. |
| pyproject.toml | Updated as part of this pull request. |
| LONG_DESCRIPTION.rst | Updated as part of this pull request. |
| CONTRIBUTING.md | Updated as part of this pull request. |
| ably/vcdiff/__init__.py | Updated as part of this pull request. |
| ably/pubsub/version.py | Updated as part of this pull request. |
| ably/pubsub/vcdiff/defaultvcdiffdecoder.py | Updated as part of this pull request. |
| ably/pubsub/vcdiff/__init__.py | Updated as part of this pull request. |
| ably/pubsub/util/nocrypto.py | Updated as part of this pull request. |
| ably/pubsub/util/helper.py | Updated as part of this pull request. |
| ably/pubsub/util/exceptions.py | Updated as part of this pull request. |
| ably/pubsub/util/eventemitter.py | Updated as part of this pull request. |
| ably/pubsub/util/encoding.py | Updated as part of this pull request. |
| ably/pubsub/util/crypto.py | Updated as part of this pull request. |
| ably/pubsub/util/construction.py | Updated as part of this pull request. |
| ably/pubsub/util/clock.py | Updated as part of this pull request. |
| ably/pubsub/util/case.py | Updated as part of this pull request. |
| ably/pubsub/util/__init__.py | Updated as part of this pull request. |
| ably/pubsub/types/typedbuffer.py | Updated as part of this pull request. |
| ably/pubsub/types/tokenrequest.py | Updated as part of this pull request. |
| ably/pubsub/types/tokendetails.py | Updated as part of this pull request. |
| ably/pubsub/types/testoptions.py | Updated as part of this pull request. |
| ably/pubsub/types/stats.py | Updated as part of this pull request. |
| ably/pubsub/types/presence.py | Updated as part of this pull request. |
| ably/pubsub/types/options.py | Updated as part of this pull request. |
| ably/pubsub/types/operations.py | Updated as part of this pull request. |
| ably/pubsub/types/mixins.py | Updated as part of this pull request. |
| ably/pubsub/types/message.py | Updated as part of this pull request. |
| ably/pubsub/types/flags.py | Updated as part of this pull request. |
| ably/pubsub/types/device.py | Updated as part of this pull request. |
| ably/pubsub/types/connectionstate.py | Updated as part of this pull request. |
| ably/pubsub/types/connectionerrors.py | Updated as part of this pull request. |
| ably/pubsub/types/connectiondetails.py | Updated as part of this pull request. |
| ably/pubsub/types/channelsubscription.py | Updated as part of this pull request. |
| ably/pubsub/types/channelstate.py | Updated as part of this pull request. |
| ably/pubsub/types/channeloptions.py | Updated as part of this pull request. |
| ably/pubsub/types/channelmode.py | Updated as part of this pull request. |
| ably/pubsub/types/channeldetails.py | Updated as part of this pull request. |
| ably/pubsub/types/capability.py | Updated as part of this pull request. |
| ably/pubsub/types/authoptions.py | Updated as part of this pull request. |
| ably/pubsub/types/annotation.py | Updated as part of this pull request. |
| ably/pubsub/types/__init__.py | Updated as part of this pull request. |
| ably/pubsub/transport/websockettransport.py | Updated as part of this pull request. |
| ably/pubsub/transport/defaults.py | Updated as part of this pull request. |
| ably/pubsub/transport/__init__.py | Updated as part of this pull request. |
| ably/pubsub/server/sync.py | Updated as part of this pull request. |
| ably/pubsub/scripts/unasync.py | Updated as part of this pull request. |
| ably/pubsub/scripts/__init__.py | Updated as part of this pull request. |
| ably/pubsub/request/paginatedresult.py | Updated as part of this pull request. |
| ably/pubsub/request/httputils.py | Updated as part of this pull request. |
| ably/pubsub/request/http.py | Updated as part of this pull request. |
| ably/pubsub/request/__init__.py | Updated as part of this pull request. |
| ably/pubsub/realtime/realtime.py | Updated as part of this pull request. |
| ably/pubsub/realtime/presencemap.py | Updated as part of this pull request. |
| ably/pubsub/realtime/presence.py | Updated as part of this pull request. |
| ably/pubsub/realtime/connectionmanager.py | Updated as part of this pull request. |
| ably/pubsub/realtime/connection.py | Updated as part of this pull request. |
| ably/pubsub/realtime/channel.py | Updated as part of this pull request. |
| ably/pubsub/realtime/annotations.py | Updated as part of this pull request. |
| ably/pubsub/realtime/__init__.py | Updated as part of this pull request. |
| ably/pubsub/prototypes.py | Updated as part of this pull request. |
| ably/pubsub/http/push.py | Updated as part of this pull request. |
| ably/pubsub/http/http.py | Updated as part of this pull request. |
| ably/pubsub/http/channel.py | Updated as part of this pull request. |
| ably/pubsub/http/auth.py | Updated as part of this pull request. |
| ably/pubsub/http/annotations.py | Updated as part of this pull request. |
| ably/pubsub/http/__init__.py | Updated as part of this pull request. |
| ably/__init__.py | Updated as part of this pull request. |
| .gitignore | Updated as part of this pull request. |
| .github/workflows/release.yml | Updated as part of this pull request. |
| .claude/skills/uts-to-python/SKILL.md | Updated as part of this pull request. |
| .claude/skills/release/SKILL.md | Updated as part of this pull request. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| name: python-package-distributions | ||
| path: dist/ | ||
| - name: Check that wheel and tarball contains ably/sync/ | ||
| - name: Check that wheel and tarball contains ably/pubsub/sync/ |
| """ | ||
|
|
||
| api_version = '5' | ||
| lib_version = '3.1.4' |
| @@ -1,9 +1,9 @@ | |||
| [project] | |||
| name = "ably" | |||
| name = "ably-pubsub-server" | |||
Publish the SDK as `ably-pubsub-server` rather than `ably`, installing into `ably/pubsub` so that further per-product distributions can share the `ably` namespace. All existing code moves to `ably/pubsub` unchanged; the public API is now reached through `ably.pubsub.server`. Neither `ably` nor `ably.pubsub` carries an `__init__.py` — both are PEP 420 namespace packages. This matters for the next distribution: a regular package wins outright over any namespace portion during import resolution, so an `ably/pubsub/__init__.py` here would silently shadow an `ably/pubsub/client` installed under a different sys.path entry, which is exactly what an editable checkout of this repo alongside a released sibling looks like. Consequences of having no package root to put things in: - `api_version` and `lib_version` move to `ably/pubsub/version.py`, as `http/httputils.py` and `types/options.py` read them and core code must not depend on the server package. - The NullHandler silencing the library's loggers moves to `ably/pubsub/util/__init__.py`, the one module every entry point imports. - unasync writes the sync tree to `ably/pubsub/sync` and maps `ably.pubsub.server` onto the hand-written `ably.pubsub.server.sync`. Also fix `HttpUtils.default_headers()`, which read `api_version` and `lib_version` off the `ably` namespace and so raised AttributeError. Only the integration tests cover the Ably-Agent header, so the unit suite was silent on it. Tests import from `ably.pubsub.server`; UPDATING.md covers the 4.0.0 migration. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Expose create_http_client() and create_realtime_client() as the only way to build a client, so that the package a client comes from names the side the application runs on. AblyRest and AblyRealtime are no longer exported from ably.pubsub.server and raise TypeError when constructed directly, naming the factory to reach for instead; a ContextVar opened by the factories is what separates a permitted construction from a direct one. Callers who annotated against the client classes should use the prototypes the factories return. ably/pubsub/prototypes.py declares RestClient and RealtimeClient as typing.Protocol definitions of the client surface, which the concrete classes satisfy structurally. They are called prototypes because "protocol" already means the Ably wire protocol here. - typing.Protocol makes 3.8 the minimum supported Python, which the CI matrix and README already assumed. requires-python and the classifiers now say so, which in turn retires two dead sys.version_info blocks in the tests. - Expand the factory docstrings to cover every client option, grouped by concern and derived from Options and AuthOptions rather than copied from the constructors. - Drop `keep_alive` from the AblyRest docstring. It has been documented since the constructor was written, but no option of that name exists and passing it raises TypeError. test/unit/pubsub_server_test.py covers the factories, the guard — including that permission does not leak past a factory call — the classes being unexported, and the concrete clients satisfying their prototypes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The distribution was renamed to ably-pubsub-server, so the agent header should no longer identify the library as ably-python. Report the SDK as ably-pubsub-python and add a versionless ably-pubsub-server agent entry so requests are attributable to the server package. Update the Ably-Agent assertion in the REST HTTP tests to match the new header format. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nflicts - Updated `protocol_members` to handle protocol attribute detection more accurately, relying on `typing._get_protocol_attrs` where available, avoiding unintended attribute inclusion. - Renamed `ably` test client to `app_setup_client` to prevent shadowing the imported `ably` package and ensure correct resolution during test execution. - Adjusted `pyproject.toml` to configure `ruff` for consistent lint behavior in both local and CI environments.
The public entry point is create_http_client, but everything behind it was named "rest": the ably.pubsub.rest package, AblyRest, and the RestClient prototype. Rename that surface to "http" so the names a caller reads match the name they call. The transport package already holding ably.pubsub.http — Http, HttpUtils and PaginatedResult — moves to ably.pubsub.request to free the name, which also describes it better: it models individual requests, not the client. - ably/pubsub/rest/ -> ably/pubsub/http/, with rest.py -> http.py - AblyRest -> AblyHttp, RestAnnotations -> HttpAnnotations, RestChannels -> HttpChannels - the exported prototypes RestClient and RealtimeClient become PubSubHttpClient and PubSubRealtimeClient - test/ably/rest/ -> test/ably/http/, rest*_test.py -> http*_test.py, TestRest* -> TestHttp* unasync's rename list, mocked-path replacements and test directories follow the move, so the generated synchronous flavour lands at ably.pubsub.sync.http. The spec-defined options rest_host and idempotent_rest_publishing keep their names, as does "REST" where it refers to the Ably API rather than to a symbol. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Nothing connected AblyHttp and AblyRealtime to the prototypes the factories return. A hasattr loop in the tests was the only check, and it was weak enough to call a class with no implemented members conformant. Have each client name its prototype as a base class, so the relationship is stated where the client is defined and a type checker verifies it. That alone would weaken the runtime check, because an unimplemented member then resolves to the prototype's `...` stub and returns None rather than raising, so the conformance tests are strengthened to match: - the prototype must actually appear in the client's MRO - every member must be defined by the client itself, found by dropping the prototype's own MRO so an inherited stub cannot satisfy it - parameter names, kinds and requiredness must match the prototype, as must whether the member is awaitable The synchronous client is covered too, since unasync generates both sides of that pair. Annotations are excluded from the signature comparison: the prototype spells its types as strings under `from __future__ import annotations` while the clients evaluate theirs, and return types are a type checker's concern. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The clients now declare their prototype as a base class, so calling them AblyHttp and AblyRealtime left the two halves of each pair reading as unrelated types. Name each class after what it is: the default implementation of its prototype. - AblyHttp -> DefaultPubSubHttpClient - AblyRealtime -> DefaultPubSubRealtimeClient - AblyHttpSync -> DefaultPubSubHttpClientSync, through unasync's rename list Neither name is exported, and both are reachable only through create_http_client and create_realtime_client; each class docstring now says as much. Tidy the 4.0.0 migration notes in passing. They no longer spell out the internal rename, which was never part of the public API. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The library now reports itself as `ably-pubsub-python/<version>`, which the two Ably-Agent tests that came in from main did not expect. - The mock websocket helper test looked for `ably-python` and now looks for the new name. - `RSC7d/ably-agent-header-format-0` asserts `ably-[a-z]+/<semver>`, which rejects a hyphenated library name. RSC7d1 puts no limit on the characters of a product key, so the specification is at fault rather than the SDK. The test is gated with `@spec_error` and the fault is recorded in deviations.md. `update_message()` takes a `Message`, and the migration guide tells users to import types like it from `ably.pubsub.server`, but neither server package exported it. Export it from both. The README passed the API key positionally to `create_realtime_client`, which accepts keyword arguments only and so raised TypeError. Pass it as `key=`, and say in the migration guide that the factories no longer accept a positional key. The release job still read the version from `dist/ably-*.tar.gz` and pointed both environments at `/p/ably`. The sdist is now `ably_pubsub_server-<version>.tar.gz`, so the tag check would never have matched it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
`batch_publish` (RSC22) posts one `BatchPublishSpec`, or a list of them, to `/messages`, encoding each message per RSL4 and applying RSL1k1 to each spec separately when idempotent REST publishing is on (RSC22d). The server answers with an array holding a `BatchResult` per spec, so a single spec gets the one element back and a list gets the list. A spec naming no channels or carrying no messages is refused locally with the 400/40000 the server would answer it with. `batch_presence` (RSC24) sends the channel names comma-joined in the `channels` parameter of a GET to `/presence`, and returns the server's `BatchResult`. The server leaves `presence` out for a channel with no members, which is read as an empty list. Both methods are declared on `PubSubHttpClient`, so the realtime and synchronous clients carry them too. `BatchResult`, `BatchPublishSpec` and the four per-channel result types (BAR2, BSP2, BPR2, BPF2, BGR2, BGF2) are exported from `ably.pubsub.server` and `ably.pubsub.server.sync`. A dict with `channels` and `messages` keys stands in for a `BatchPublishSpec`, as a dict does for the push admin types. The RSL1k1 id assignment moves out of `Channel` into `assign_idempotent_ids`, which both publish paths share. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The 44 batch Test IDs (47 cases) across `rest/unit` and `rest/integration` drop their `@deviation` gates and pass. They now build `BatchPublishSpec` and check result types with `isinstance`, as the specifications write them. Every `batch_publish.md` mock answers in the legacy format, a flat array of per-channel results, which the sandbox sends only to a client sending `X-Ably-Version: 2` or none. At version 5, which ably-python sends, `POST /messages` answers every batch, mixed and all-failure ones included, with 201 and an array holding one `BatchResult` envelope per spec, a single spec sent as a bare object included. The fixtures are corrected to that shape through `batch_result()`, and the assertions stand. Two RSL4c3 assertions compared a stringified JSON payload byte for byte; they now parse it, as the encoding tests do, since the specification does not fix the whitespace. deviations.md drops the batch row from Unimplemented features, and rewrites the envelope entry: it had concluded that `batch_presence.md` was the specification to revisit, and the server says it is `batch_publish.md`. The header and measured counts are re-measured: 172 gated cases, the RSC7d `Ably-Agent` test among them, 1047 passing derived cases, and 130 helper cases where 122 had been recorded. Three Smaller faults rows that had been superseded by their filed copies are removed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The batch publish and token revocation fixtures written in the response format below protocol version 3 are filed as ably/specification#559. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
4.0 makes ably.pubsub.server the whole public API, but its export list was carried over from 3.x's top-level ably package, which only re-exported CipherParams. 3.x users reached generate_random_key and get_default_params through ably.util.crypto, a submodule that 4.0 moves and declares internal, so 4.0 left no public way to generate a key (RSE2) or build default cipher params. Export both from ably.pubsub.server and ably.pubsub.server.sync, show the 3.x to 4.0 import in UPDATING.md, and make the missing-crypto error name the ably-pubsub-server[crypto] extra instead of the old ably[crypto].
Export generate_random_key and get_default_params from ably.pubsub.server
feat: add batch publish and batch presence to the HTTP client
Derives the fifteen specifications under uts/objects/unit, 322 tests, and the shared helper uts/objects/helpers/standard_test_pool.md describes: the standard pool, its wire builders, the synced-channel setup and the REST provisioning the integration tier uses. The pure specifications drive the CRDT objects, the pool and the sync state machine directly; the rest run against a mock websocket through channel.object. The public API is reached through the typed views of LODR-061, so a specification's untyped value(), set() or entries() reads as as_live_counter().value(), as_live_map().set() and so on. Where a specification step cannot fail, or reads state before the frame that changes it has been processed, the test carries the corrected step under a UTS SPEC ERROR comment and keeps the specification's own assertions. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Derives the three sandbox specifications under uts/objects/integration and the proxy specification under uts/objects/integration/proxy, 17 tests. The sandbox ones run under both protocols, against an app of their own; the proxy ones authenticate with a locally signed JWT, as the realtime proxy tier does, and fault the objects sync through uts-proxy. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Adds the ably.pubsub.objects package: the protocol v6 object message wire types, with their JSON and msgpack encodings; the LWW map and counter CRDTs with their tombstones, parent references and garbage collection; the objects pool and the sync sequence that replaces it on attach, buffering operations until the sync completes; object id generation; the evaluation of LiveMap and LiveCounter creation values into create operations; and the public ObjectMessage the subscription events carry. A RealtimeObject can be built with no channel, which is how the pure unit specifications drive the sync state machine. The path-based public API, publishing and the channel integration follow in later commits and are stubs here. Also adds the HAS_OBJECTS flag, the OBJECT_SUBSCRIBE and OBJECT_PUBLISH channel modes, and the siteCode and objectsGCGracePeriod connection details. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Routes ATTACHED, OBJECT and OBJECT_SYNC to the channel's RealtimeObject, and every other channel state change to it, so that each attach starts an objects sync and a detached or failed channel clears its objects. The transport now hands OBJECT and OBJECT_SYNC frames to the channel at all. RealtimeObject.get() attaches the channel through the RTL33 ensure-active-channel procedure and waits for the sync; a write publishes an OBJECT message and, once its ACK assigns serials, applies the operations locally rather than waiting for the echo. The internal counter and map gain their increment, decrement, set and remove, and the GC sweep runs on the client's clock while the channel is attached. Connects with protocol version 6, whose wire format the objects messages use, and identifies to REST as version 6 to match. Adds the echo_messages client option, sent as the echo connect parameter, which LiveObjects writes require. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Implements the public API LODR-061 specifies. A PathObject names a location in the channel's object tree and resolves it on every call, so it keeps working as the objects at that path are replaced; an Instance holds one object and follows it wherever it moves. Each has a base class carrying navigation, instance(), compact() and compact_json(), and three views, as_live_map(), as_live_counter() and as_primitive(), that carry the methods specific to a type. The path views are unchecked, because a path's type can change under it: a read through the wrong view answers None and a write raises 92005 or 92007. The instance views check, and raise 92007 at once. Path subscriptions are dispatched from every object update to each path the updated object can be reached by, filtered by depth, with the public ObjectMessage describing the operation. The LiveObjects public names are exported from ably.pubsub.server. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Adds the batch API LODR-061 specifies, from the RTBC section of ably/specification#471: `async with root.batch() as ctx:` resolves the target once, and the writes made through the context inside the block are queued and published as a single OBJECT message when the block exits, so other clients see them as one update. Reads inside the block resolve against the local tree; a block that raises publishes nothing, and a context used after its block has closed raises 40000. batch() is on the map and counter views of both PathObject and Instance, which is what types the context. LiveMap and LiveCounter values are evaluated when the batch is published, since creating them reads the server time. No UTS specification covers the batch API or the typed views of LODR-061 yet, so test/unit/objects tests both against their spec points. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Adds the objects tier to deviations.md: the faults in the uts/objects specifications the derived tests correct or work around, the shape adaptations the Python API forces, the claims investigated and refuted against the sandbox, seven candidate upstream issues, and how the tier is adopted here. The header counts are re-measured with objects as a tier of its own, which also corrects the gated count: the RSC7d spec-error gate was never counted in it. The UTS README and the uts-to-python skill gain the objects layout, its helpers, the typed-view translation and the traps met deriving it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
get() and a write waiting for the objects sync now fail with 92008 when the channel is already detached, failed or released, rather than only when it moves into one of those states while they wait; before, closing the client during get()'s attach, or an ERROR arriving with the ACK, left the wait pending forever. The RTL33 ensure-active-channel step checks the state the implicit attach ended in, and a write is no longer applied locally once the channel's objects have been cleared. An object message that fails to decode, or an operation that raises while being applied, is logged and skipped on its own, so one bad value cannot drop the rest of its OBJECT message, or an OBJECT_SYNC's cursor and so the whole sync. A released channel stops its GC timer, and a sweep that raises is logged and rescheduled. Also shares the MAP_SET, MAP_REMOVE and COUNTER_INC construction between the direct writes and the batch, validates a LiveMap or LiveCounter value before reading the server time, keeps the GC grace period from each CONNECTED, and lets typing.get_type_hints resolve the wire dataclasses. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ably-java and ably-cocoa expose only compactJson, and RTTS3f and RTTS7d let a typed SDK leave compact out. In Python the two would return dicts that differ only once the data holds bytes or a shared map, and json.dumps raises on compact's result at exactly that point. LODR-061 records the choice. compact_json returns JsonValue, exported with JsonObject from ably.pubsub.server, and LiveMapInstance and LiveCounterInstance narrow it per RTTS7a. The UTS compact tests read through compact_json, recorded as adaptation S-6. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Moves ably.pubsub.objects to ably.pubsub.liveobjects, and its unit tests to test/unit/liveobjects, following PDR-080: package and import names carry the product name, while the API keeps the resource name, so channel.object, RealtimeObject and ObjectMessage are unchanged. test/uts/objects keeps the specification's directory name, so each derived test still maps onto the uts/objects specification it comes from. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Moves the thirty LiveObjects names out of ably.pubsub.server into a module
of their own, alongside ably.pubsub.server.sync. Generic names such as
Batch, Subscription, Instance and Primitive no longer share a namespace
with the Pub/Sub ones, where Batch read as part of batch publish next to
BatchResult and BatchPublishSpec, and the product name shows at the
import, as PDR-080 asks:
from ably.pubsub.server.liveobjects import LiveCounter, LiveMap
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
_decode_number passed any value that was not an int or a float through unchanged, so a counter increment or count sent as a string decoded and only failed later, in the counter's arithmetic. It now raises ValueError for a present value of any other type, so from_protocol_message skips the ObjectMessage carrying it at decode time. The RTO9 and RTO5c tests used a string number as their operation that decodes but fails to apply; they now make the apply raise instead, and a new RTO8 test covers the string increment as a decode failure. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
feat: add LiveObjects
…ched Specification 6.3.0 replaces RTS4a with RTS4c-e. Channels.release used to remove a channel whatever its state, so an attached channel was dropped from the collection while still attached in the Ably service. It now raises an AblyException with code 90011 and status 400 for a channel that is not INITIALIZED, DETACHED or FAILED, and leaves the channel as it was (RTS4e); it still returns quietly for an unknown name (RTS4c) and removes a channel in one of those states (RTS4d). This is a breaking change: callers must await channel.detach() before releasing. 3.x logs a deprecation warning in this case (RTS4b). The channels collection UTS tests are rederived for RTS4c-e, which closes the RTS4a release deviation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
pubsub: raise 90011 when releasing a realtime channel that isn't detached


Integration branch contains packages split, renaming and deletion of deprecated methods